feat(rocm): grouped + non-grouped keep-quant expert GEMM — the MoE-path terminus (issue #41) - #523
feat(rocm): grouped + non-grouped keep-quant expert GEMM — the MoE-path terminus (issue #41)#523VikashLoomba wants to merge 2 commits into
Conversation
…mbineGate) (mudler#41) The next links in the generic MoE path after the router/silu-mul. Hand- translated from cuda_moe.cu (MoeCombineKernel :473, MoeCombineGateKernel :555) and the SharedExpertGate CPU oracle (cpu_ops.cpp:2387). Grid-stride, f32 math, bf16/f32 dtype arms via boundary conversions; the combine-gate folds the shared-expert sigmoid gate rounded through bf16 exactly as the donor. Evidence (4x gfx1100, ROCm 7.14, Release): - new MoE combine/gate cross-device case: 9/9 assertions (MoeCombineGate's oracle is the host-computed composite — no CPU op registration exists) - ctest -R 'rocm|cross_device': 4/4 - full ctest: pre-existing failure set shrinks 7 -> 5; test_bench and test_capi now PASS (they failed at op 77 / the router dtype before the chain). test_loaded_engine_dense now fails only on the async-scheduling assertion (a lane capability gap, not a kernel throw). - Named remaining blocker: the grouped quant expert GEMM (kMatmulBTQuantGrouped), the DeepSeek-V4 keep-quant family. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: pi:kimi-k3 [pi]
…ant, kMatmulBTQuantGrouped) — the MoE-path terminus (mudler#41) The last kernel blocker for GDN-MoE models on discrete ROCm. Ports the cuda_quant_dot.cu grouped + plain keep-quant GEMMs (QuantDotGemmGroupedKernel :746 / QuantDotGemmKernel :706 / the Q8_0 + Q8_K activation quantizers) and the DotQ8_0 / DotQ4K / DotQ5K / DotQ6K superblocks 1:1. Registers kMatmulBTQuant (op 74) + kMatmulBTQuantGrouped (op 75) — registering the non-grouped op flips GgufQuantComputeAvailable() so the keep-quant path actually activates on ROCm. Integer dot cores via a portable Dp4a (bit-identical to __dp4a); the HW dot instruction is a named perf lever. Evidence (4x gfx1100, ROCm 7.14, Release): - cross-device grouped-quant case: 16/16 (Q8_0/Q4_K/Q5_K/Q6_K, valid random blocks + real f32 activations, NMSE <= 5e-4 vs the CPU keep-quant oracle) - ctest -R 'rocm|cross_device': 4/4; full ctest: the 5 pre-existing host/lane failures only (test_bench + test_capi pass since the MoE chain). - E2E: Qwen3.6-35B-A3B Q4_K_M (21GB GDN-MoE GGUF) runs end to end on one gfx1100 with keep-quant active — ops 74 AND 75 resolve vt-native, zero CPU-ref fallback, correct output. Needs --max-num-seqs 1 to fit one 24GB card (the GDN state pool otherwise pushes past; residency note, not a kernel defect). A backend-Alloc instrumentation run confirmed the OOM was cumulative ~23.8 GiB = genuine capacity, not a kernel bug. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: pi:kimi-k3 [pi]
|
Reviewed as part of a sweep over the open external PRs. The GEMM port is the strongest part of this — I diffed One blocker, and it is in how the op is switched on rather than in the kernel. Registering
So a Q4_0 or Q2_K or IQ2 GGUF that loads and generates correctly on ROCm today would now keep its blocks quantized at load and throw Same flip has collateral: The fix is a per-dtype availability query rather than a boolean, or a refusal at load time rather than forward time. Related: the refusal message at Second thing, worth knowing before you invest further. The per-call Smaller: Note also that the non-grouped op — the one that carries this PR's headline mechanism — has no test at all; only On CI: the four red checks are all infrastructure, none yours. No AMD hardware here, so your 16/16, the ctest results and the 35B e2e run could not be reproduced and I am not disputing them; the finding above is read from the loader chain end to end. |
…(W1, #332) (#473) Implements the vt::Backend graph-capture seam on hipGraph (W1 of #332), mirroring src/vt/cuda/cuda_backend.cu call for call. Merged with the row's performance rationale REFUTED and recorded as such. W3 measured capture at +3.2% / +0.6% / -1.0%, not the ~2.2-3x §1 predicted, and the spec's D7 plus the inline note in §1 now say so rather than leaving a live rationale for the next agent to re-derive. That refutation was reported by the contributor against their own interest, which is the behaviour this protocol exists to produce. Merged anyway on the seam argument, which is independent of the decode number: graph capture had exactly one real implementation (CUDA), and a one-implementation abstraction is unproven. hipGraph is the cheapest available second. Runtime cost today is zero -- RocmPlatform does not override support_static_graph_mode(), so nothing in the engine reaches the new code. Review verified isolation three ways: every decode-graph call site ANDs SupportsGraphCapture() with support_static_graph_mode(); rocm_backend.hip appears zero times in a CPU build's compile_commands.json; and there is zero drift on every touched file across the 194-commit gap. A mutation of the EndCaptureGraph seam signature turns the new test red, so it genuinely guards seam drift on machines with no AMD hardware. Known-broken windows-msvc-* are the PR-only arm (#584), not this change. Carried forward: #523's per-call hipMalloc/hipFree and hipStreamSynchronize are illegal under hipGraph capture and must be reconciled before this capability could ever be switched on.
Row
BACKEND-ROCM— the last kernel blocker for MoE-bearing models on discrete ROCm. Issue #41. Stacked on #509 (MoE combine/gate chain).What changed
NEW
src/vt/rocm/rocm_grouped_gemm.hip— ports the keep-quant expert GEMM family fromcuda_quant_dot.cu1:1:kMatmulBTQuant(op 74, non-grouped) +kMatmulBTQuantGrouped(op 75, grouped overexpert_ids)DotQ8_0/DotQ4K/DotQ5K/DotQ6Ksuperblocks,__dp4a→ portableDp4a(bit-identical integer core),__shfl_down_syncreductionGgufQuantComputeAvailable()on ROCm — the grouped op alone leaves the loader dequantizing experts to bf16.Cross-device case: all four formats vs the CPU keep-quant oracle, valid random blocks + real activations.
Evidence (4× gfx1100, ROCm 7.14, Release)
ctest -R 'rocm|cross_device': 4/4; full ctest: only the 5 pre-existing host/lane failures (zero new)vt-native, zero CPU-ref fallback, correct output. Requires--max-num-seqs 1to fit one 24GB card (the GDN state pool otherwise pushes past — a residency note, not a kernel defect; confirmed via a backend-Alloc instrumentation run showing genuine cumulative ~23.8 GiB).Speed claims
Honest gaps
hipMalloc/hipFreeactivation scratch is correctness-grade; a queue-owned grow-only pool is a perf lever (decode-step churn).--max-num-seqs 1on 24GB; multi-GPU expert sharding or host streaming is the follow-on for bigger MoE / longer context.